package com.stu.javabase;

/**
 * static、final关键字和异常处理演示
 * 涵盖：
 * - static关键字的用法
 * - final关键字的用法
 * - final、finally、finalize的区别
 * - Java异常体系
 * - 异常处理机制
 * 
 * @author 学习者
 * @version 1.0
 */
public class StaticFinalAndException {
    
    // static变量（类变量）
    private static int staticCount = 0;
    private static final String CONSTANT_VALUE = "常量值";
    
    // 实例变量
    private int instanceCount = 0;
    private final String finalValue;
    
    // static代码块
    static {
        System.out.println("static代码块执行，初始化静态资源");
        staticCount = 100;
    }
    
    // 实例代码块
    {
        System.out.println("实例代码块执行");
        instanceCount = 1;
    }
    
    /**
     * 构造方法
     * @param finalValue final属性必须在构造方法中初始化
     */
    public StaticFinalAndException(String finalValue) {
        this.finalValue = finalValue;
        System.out.println("构造方法执行");
    }
    
    public static void main(String[] args) {
        System.out.println("=== static、final关键字和异常处理演示 ===");
        
        // 1. static关键字演示
        demonstrateStatic();
        
        // 2. final关键字演示
        demonstrateFinal();
        
        // 3. 异常处理演示
        demonstrateExceptions();
        
        // 4. try-catch-finally演示
        demonstrateTryCatchFinally();
    }
    
    /**
     * 演示static关键字的用法
     */
    private static void demonstrateStatic() {
        System.out.println("\n=== static关键字演示 ===");
        
        // static变量是类级别的，所有实例共享
        System.out.println("创建对象前，staticCount = " + staticCount);
        
        StaticFinalAndException obj1 = new StaticFinalAndException("对象1");
        StaticFinalAndException obj2 = new StaticFinalAndException("对象2");
        
        // 修改static变量
        staticCount = 200;
        System.out.println("修改staticCount后：");
        System.out.println("通过类名访问：StaticFinalAndException.staticCount = " + StaticFinalAndException.staticCount);
        System.out.println("通过obj1访问：obj1.staticCount = " + obj1.staticCount);
        System.out.println("通过obj2访问：obj2.staticCount = " + obj2.staticCount);
        
        // static方法调用
        staticMethod();
        
        // static常量
        System.out.println("static final常量：" + CONSTANT_VALUE);
        
        // static不能修饰局部变量
        // static int localVar = 10; // 编译错误
        
        System.out.println("\nstatic关键字特点：");
        System.out.println("1. static变量属于类，不属于任何实例");
        System.out.println("2. static方法不能访问非static成员");
        System.out.println("3. static代码块在类加载时执行，且只执行一次");
        System.out.println("4. static不能修饰局部变量");
        System.out.println("5. static方法不能被重写，但可以被隐藏");
    }
    
    /**
     * static方法
     */
    private static void staticMethod() {
        System.out.println("这是一个static方法");
        // 不能访问非static成员
        // System.out.println(instanceCount); // 编译错误
        // this.finalValue; // 编译错误
    }
    
    /**
     * 演示final关键字的用法
     */
    private static void demonstrateFinal() {
        System.out.println("\n=== final关键字演示 ===");
        
        // final变量
        final int finalVar = 10;
        // finalVar = 20; // 编译错误，final变量不能重新赋值
        System.out.println("final变量：" + finalVar);
        
        // final引用
        final StringBuilder sb = new StringBuilder("Hello");
        sb.append(" World"); // 可以修改对象内容
        // sb = new StringBuilder(); // 编译错误，不能重新赋值引用
        System.out.println("final引用对象：" + sb.toString());
        
        // final方法演示
        FinalMethodDemo demo = new FinalMethodDemo();
        demo.finalMethod();
        demo.normalMethod();
        
        // final类演示
        FinalClassExample finalClass = new FinalClassExample();
        finalClass.showInfo();
        
        System.out.println("\nfinal关键字特点：");
        System.out.println("1. final变量：一旦赋值不能改变（常量）");
        System.out.println("2. final方法：不能被子类重写");
        System.out.println("3. final类：不能被继承（如String、Integer等）");
        System.out.println("4. final引用：引用不能改变，但对象内容可以改变");
        
        // final、finally、finalize的区别
        System.out.println("\nfinal、finally、finalize的区别：");
        System.out.println("final：关键字，用于声明常量、不可重写方法、不可继承类");
        System.out.println("finally：关键字，异常处理中的代码块，总是会执行");
        System.out.println("finalize：方法，Object类的方法，垃圾回收前调用（已废弃）");
    }
    
    /**
     * 演示Java异常体系
     */
    private static void demonstrateExceptions() {
        System.out.println("\n=== Java异常体系演示 ===");
        
        System.out.println("Java异常体系结构：");
        System.out.println("Throwable");
        System.out.println("├── Error（错误）");
        System.out.println("│   ├── OutOfMemoryError");
        System.out.println("│   ├── StackOverflowError");
        System.out.println("│   └── ...");
        System.out.println("└── Exception（异常）");
        System.out.println("    ├── RuntimeException（运行时异常，非受检异常）");
        System.out.println("    │   ├── NullPointerException");
        System.out.println("    │   ├── ArrayIndexOutOfBoundsException");
        System.out.println("    │   ├── IllegalArgumentException");
        System.out.println("    │   └── ...");
        System.out.println("    └── 受检异常（编译时异常）");
        System.out.println("        ├── IOException");
        System.out.println("        ├── SQLException");
        System.out.println("        └── ...");
        
        // 常见运行时异常演示
        demonstrateRuntimeExceptions();
        
        // throw和throws的区别
        demonstrateThrowAndThrows();
    }
    
    /**
     * 演示常见的运行时异常
     */
    private static void demonstrateRuntimeExceptions() {
        System.out.println("\n常见运行时异常演示：");
        
        // 1. NullPointerException
        try {
            String str = null;
            int length = str.length(); // 空指针异常
        } catch (NullPointerException e) {
            System.out.println("1. NullPointerException: " + e.getMessage());
        }
        
        // 2. ArrayIndexOutOfBoundsException
        try {
            int[] arr = {1, 2, 3};
            int value = arr[5]; // 数组越界
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("2. ArrayIndexOutOfBoundsException: " + e.getMessage());
        }
        
        // 3. NumberFormatException
        try {
            int num = Integer.parseInt("abc"); // 数字格式异常
        } catch (NumberFormatException e) {
            System.out.println("3. NumberFormatException: " + e.getMessage());
        }
        
        // 4. ClassCastException
        try {
            Object obj = "Hello";
            Integer num = (Integer) obj; // 类型转换异常
        } catch (ClassCastException e) {
            System.out.println("4. ClassCastException: " + e.getMessage());
        }
        
        // 5. IllegalArgumentException
        try {
            Thread.sleep(-1); // 非法参数异常
        } catch (IllegalArgumentException e) {
            System.out.println("5. IllegalArgumentException: " + e.getMessage());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException: " + e.getMessage());
        }
    }
    
    /**
     * 演示throw和throws的区别
     */
    private static void demonstrateThrowAndThrows() {
        System.out.println("\nthrow和throws的区别：");
        System.out.println("throw：用于主动抛出异常");
        System.out.println("throws：用于声明方法可能抛出的异常");
        
        try {
            methodWithThrows(0);
        } catch (IllegalArgumentException e) {
            System.out.println("捕获到异常：" + e.getMessage());
        }
        
        try {
            methodWithThrow(-1);
        } catch (RuntimeException e) {
            System.out.println("捕获到异常：" + e.getMessage());
        }
    }
    
    /**
     * 使用throws声明异常的方法
     * @param value 参数值
     * @throws IllegalArgumentException 当参数为0时抛出
     */
    private static void methodWithThrows(int value) throws IllegalArgumentException {
        if (value == 0) {
            throw new IllegalArgumentException("参数不能为0");
        }
        System.out.println("方法正常执行，参数值：" + value);
    }
    
    /**
     * 使用throw主动抛出异常的方法
     * @param value 参数值
     */
    private static void methodWithThrow(int value) {
        if (value < 0) {
            throw new RuntimeException("参数不能为负数"); // 主动抛出异常
        }
        System.out.println("方法正常执行，参数值：" + value);
    }
    
    /**
     * 演示try-catch-finally的执行顺序
     */
    private static void demonstrateTryCatchFinally() {
        System.out.println("\n=== try-catch-finally演示 ===");
        
        // 1. 正常执行情况
        System.out.println("\n1. 正常执行情况：");
        try {
            System.out.println("try块执行");
            int result = 10 / 2;
            System.out.println("计算结果：" + result);
        } catch (ArithmeticException e) {
            System.out.println("catch块执行：" + e.getMessage());
        } finally {
            System.out.println("finally块执行");
        }
        
        // 2. 异常情况
        System.out.println("\n2. 异常情况：");
        try {
            System.out.println("try块执行");
            int result = 10 / 0; // 除零异常
            System.out.println("这行不会执行");
        } catch (ArithmeticException e) {
            System.out.println("catch块执行：" + e.getMessage());
        } finally {
            System.out.println("finally块执行");
        }
        
        // 3. try中有return的情况
        System.out.println("\n3. try中有return的情况：");
        int result = methodWithReturnInTry();
        System.out.println("方法返回值：" + result);
        
        // 4. finally中有return的情况（不推荐）
        System.out.println("\n4. finally中有return的情况：");
        int result2 = methodWithReturnInFinally();
        System.out.println("方法返回值：" + result2);
        
        System.out.println("\ntry-catch-finally特点：");
        System.out.println("1. finally块总是会执行（除非JVM退出）");
        System.out.println("2. catch块可以省略，但try-finally必须配对");
        System.out.println("3. finally中的return会覆盖try/catch中的return");
        System.out.println("4. finally适合做资源清理工作");
    }
    
    /**
     * try中有return的方法
     * @return 返回值
     */
    private static int methodWithReturnInTry() {
        try {
            System.out.println("try块中准备return");
            return 1;
        } catch (Exception e) {
            System.out.println("catch块执行");
            return 2;
        } finally {
            System.out.println("finally块执行（try中有return）");
            // 注意：这里不要return，否则会覆盖try中的return
        }
    }
    
    /**
     * finally中有return的方法（不推荐的写法）
     * @return 返回值
     */
    private static int methodWithReturnInFinally() {
        try {
            System.out.println("try块中准备return");
            return 1;
        } catch (Exception e) {
            System.out.println("catch块执行");
            return 2;
        } finally {
            System.out.println("finally块执行并return（会覆盖try中的return）");
            return 3; // 这会覆盖try中的return值
        }
    }
    
    /**
     * 重写finalize方法（已废弃，仅作演示）
     */
    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize方法被调用（对象即将被垃圾回收）");
        super.finalize();
    }
}

/**
 * final方法演示类
 */
class FinalMethodDemo {
    /**
     * final方法，不能被重写
     */
    public final void finalMethod() {
        System.out.println("这是一个final方法，不能被重写");
    }
    
    /**
     * 普通方法，可以被重写
     */
    public void normalMethod() {
        System.out.println("这是一个普通方法，可以被重写");
    }
}

/**
 * final类演示（不能被继承）
 */
final class FinalClassExample {
    public void showInfo() {
        System.out.println("这是一个final类，不能被继承");
    }
}

// class CannotExtend extends FinalClassExample {} // 编译错误，不能继承final类